package com.ruoyi.leave.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.leave.domain.WorkflowWaterMonthPlan;
import com.ruoyi.leave.domain.dto.WorkflowWaterMonthPlanDTO;
import com.ruoyi.leave.domain.vo.WorkflowWaterMonthPlanVO;
import com.ruoyi.leave.mapper.WorkflowWaterMonthPlanMapper;
import com.ruoyi.leave.service.IWorkflowWaterMonthPlanService;
import com.ruoyi.leave.util.WorkFlowCache;
import com.ruoyi.leave.util.WorkFlowConstants;
import com.ruoyi.manage.domain.BtFlowHistory;
import com.ruoyi.manage.domain.SwWaterMonthReport;
import com.ruoyi.manage.domain.dto.Plan;
import com.ruoyi.manage.service.IBtFlowHistoryService;
import com.ruoyi.manage.service.ISwWaterMonthReportService;
import lombok.extern.slf4j.Slf4j;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用水月度计划申请Service业务层处理
 *
 * @author ruoyi
 * @date 2024-01-04
 */
@Service
@Slf4j
public class WorkflowWaterMonthPlanServiceImpl implements IWorkflowWaterMonthPlanService {

    @Autowired
    private WorkflowWaterMonthPlanMapper workflowWaterMonthPlanMapper;

    @Autowired
    private WorkFlowCache workFlowCache;

    @Autowired
    private ProcessRuntime processRuntime;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ISwWaterMonthReportService swWaterMonthReportService;

    @Resource
    private DynamicJumpService dynamicJumpService;

    @Autowired
    private IBtFlowHistoryService btFlowHistoryService;


    /**
     * 查询用水月度计划申请
     *
     * @param id 用水月度计划申请ID
     * @return 用水月度计划申请
     */
    @Override
    public WorkflowWaterMonthPlan selectWorkflowWaterMonthPlanById(String id) {
        return workflowWaterMonthPlanMapper.selectWorkflowWaterMonthPlanById(id);
    }

    /**
     * 查询用水月度计划申请列表
     *
     * @param workflowWaterMonthPlan 用水月度计划申请
     * @return 用水月度计划申请
     */
    @Override
    @DataScope(deptAlias = "sd", userAlias = "wwmp")
    public List<WorkflowWaterMonthPlan> selectWorkflowWaterMonthPlanList(WorkflowWaterMonthPlan workflowWaterMonthPlan) {
        return workflowWaterMonthPlanMapper.selectWorkflowWaterMonthPlanList(workflowWaterMonthPlan);
    }

    /**
     * 新增用水月度计划申请
     *
     * @param workflowWaterMonthPlan 用水月度计划申请
     * @return 结果
     */
    @Override
    @Transactional(readOnly = false,rollbackFor = Exception.class)
    public int insertWorkflowWaterMonthPlan(WorkflowWaterMonthPlan workflowWaterMonthPlan) {
        // 月度上报汇总表基础信息
        SwWaterMonthReport swWaterMonthReport = swWaterMonthReportService.selectSwWaterMonthReportById(workflowWaterMonthPlan.getPlanId());
        if("0".equals(swWaterMonthReport.getType())){
            // 农业
            workflowWaterMonthPlan.setChannel("2");
        } else {
            // 工业
            workflowWaterMonthPlan.setChannel("1");
        }
        workflowWaterMonthPlan.setDeptId(swWaterMonthReport.getDeptId());

        String id = UUID.randomUUID().toString();
        workflowWaterMonthPlan.setId(id);
        workflowWaterMonthPlan.setCreateTime(DateUtils.getNowDate());
        workflowWaterMonthPlan.setPlanId(workflowWaterMonthPlan.getPlanId());
        workflowWaterMonthPlan.setChannel(workflowWaterMonthPlan.getChannel());
        ProcessInstance processInstance = startProcess(workflowWaterMonthPlan);
        List<String> userRoles = SecurityUtils.getLoginUser().getUser().getRoles().stream().map(SysRole::getRoleKey).collect(Collectors.toList());
        String processDefinitionKey = WorkFlowConstants.WATER_PLAN_CHANNEL.getEnum(workflowWaterMonthPlan.getChannel(), "month").getName();
        Task firstUserTask = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskCandidateGroupIn(userRoles)
                .processDefinitionKey(processDefinitionKey).singleResult();
        taskService.claim(firstUserTask.getId(), SecurityUtils.getLoginUser().getUsername());
        taskService.setAssignee(firstUserTask.getId(), SecurityUtils.getLoginUser().getUsername());
        taskService.setVariableLocal(firstUserTask.getId(), "userName", SecurityUtils.getLoginUser().getUsername());
        taskService.setVariableLocal(firstUserTask.getId(), "depId", SecurityUtils.getLoginUser().getUser().getDeptId());
        taskService.complete(firstUserTask.getId());
        Map<String, UserTask> userTaskList = workFlowCache.getUserTaskList(processInstance.getProcessDefinitionId());
        workflowWaterMonthPlan.setRolegroup(userTaskList.get(firstUserTask.getTaskDefinitionKey()).getFormKey().split("#")[1]);
        workflowWaterMonthPlan.setInstanceId(processInstance.getId());
        workflowWaterMonthPlan.setState(WorkFlowConstants.WATER_PLAN_STATUS_ENUM.INIT.getValue());
        workflowWaterMonthPlan.setCreateName(SecurityUtils.getNickName());
        workflowWaterMonthPlan.setCreateBy(SecurityUtils.getUsername());
        workflowWaterMonthPlan.setCreateTime(DateUtils.getNowDate());

        swWaterMonthReport.setStatus("1");
        swWaterMonthReport.setSubmitTime(new Date());
        swWaterMonthReportService.updateSwWaterMonthReport(swWaterMonthReport);

        // 增加审批日志明细
        BtFlowHistory btFlowHistory = new BtFlowHistory();
        btFlowHistory.setcDate(new Date());
        SysUser user = SecurityUtils.getLoginUser().getUser();
        btFlowHistory.setUserId(user.getUserId());
        btFlowHistory.setUserName(user.getNickName());
        btFlowHistory.setStatus("1");
        btFlowHistory.setReason("提交");
        btFlowHistory.setServiceId(workflowWaterMonthPlan.getPlanId());
        btFlowHistoryService.insertBtFlowHistory(btFlowHistory);

        return workflowWaterMonthPlanMapper.insertWorkflowWaterMonthPlan(workflowWaterMonthPlan);
    }

    private ProcessInstance startProcess(WorkflowWaterMonthPlan workflowWaterMonthPlan) {
        Map<String, Object> processVariableMap = new HashMap<>();
        processVariableMap.put("planId", workflowWaterMonthPlan.getPlanId());
        processVariableMap.put("workflowWaterPlanId", workflowWaterMonthPlan.getId());
        processVariableMap.put("channel", workflowWaterMonthPlan.getChannel());
        processVariableMap.put("startDepId", SecurityUtils.getLoginUser().getUser().getDeptId());
        String processDefinitionKey = WorkFlowConstants.WATER_PLAN_CHANNEL.getEnum(workflowWaterMonthPlan.getChannel(), "month").getName();
        processVariableMap.put("key", processDefinitionKey);
        ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
                .start()
                .withProcessDefinitionKey(processDefinitionKey)
                .withBusinessKey(workflowWaterMonthPlan.getId())
                .withVariables(processVariableMap)
                .withName(Objects.requireNonNull(WorkFlowConstants.WATER_PLAN_CHANNEL.getEnum(workflowWaterMonthPlan.getChannel(), "month")).getLabel())
                .build());
        return processInstance;
    }

    /**
     * 修改用水月度计划申请
     *
     * @param workflowWaterMonthPlan 用水月度计划申请
     * @return 结果
     */
    @Override
    public int updateWorkflowWaterMonthPlan(WorkflowWaterMonthPlan workflowWaterMonthPlan) {
        workflowWaterMonthPlan.setUpdateTime(DateUtils.getNowDate());
        return workflowWaterMonthPlanMapper.updateWorkflowWaterMonthPlan(workflowWaterMonthPlan);
    }

    /**
     * 批量删除用水月度计划申请
     *
     * @param ids 需要删除的用水月度计划申请ID
     * @return 结果
     */
    @Override
    public int deleteWorkflowWaterMonthPlanByIds(String[] ids) {
        return workflowWaterMonthPlanMapper.deleteWorkflowWaterMonthPlanByIds(ids);
    }

    /**
     * 删除用水月度计划申请信息
     *
     * @param id 用水月度计划申请ID
     * @return 结果
     */
    @Override
    public int deleteWorkflowWaterMonthPlanById(String id) {
        return workflowWaterMonthPlanMapper.deleteWorkflowWaterMonthPlanById(id);
    }

    @Override
    public void claimTask(WorkflowWaterMonthPlan workflowWaterMonthPlan) {
        List<String> roles = StrUtil.split(workflowWaterMonthPlan.getRolegroup(), ",");
        Task task = taskService.createTaskQuery().processInstanceId(workflowWaterMonthPlan.getInstanceId()).singleResult();
        String username = SecurityUtils.getUsername();
        if (Objects.isNull(task)) {
            log.info("{}没找到可以拾取的任务", username);
            throw new CustomException(username + "没找到可以拾取的任务");
        }
        taskService.claim(task.getId(), username);
        workflowWaterMonthPlan.setAssignee(username);
        workflowWaterMonthPlan.setState(WorkFlowConstants.WATER_PLAN_STATUS_ENUM.WAIT_CHECK.getValue());
        workflowWaterMonthPlan.setUpdateTime(new Date());
        workflowWaterMonthPlan.setUpdateBy(username);
        workflowWaterMonthPlanMapper.updateWorkflowWaterMonthPlan(workflowWaterMonthPlan);

    }

    @Override
    public void unClaimTask(WorkflowWaterMonthPlan workflowWaterMonthPlan) {
        List<String> roles = StrUtil.split(workflowWaterMonthPlan.getRolegroup(), ",");
        String username = SecurityUtils.getUsername();
        Task task = taskService.createTaskQuery().taskCandidateGroupIn(roles).processInstanceId(workflowWaterMonthPlan.getInstanceId()).singleResult();
        if (Objects.isNull(task)) {
            log.info("{}没找到可以归还的任务", username);
            return;
        }
        taskService.unclaim(task.getId());
        workflowWaterMonthPlan.setAssignee(null);
        workflowWaterMonthPlan.setState(WorkFlowConstants.WATER_PLAN_STATUS_ENUM.WAIT_CHECK.getValue());
        workflowWaterMonthPlan.setUpdateTime(new Date());
        workflowWaterMonthPlan.setUpdateBy(username);
        workflowWaterMonthPlanMapper.updateWorkflowWaterMonthPlan(workflowWaterMonthPlan);
    }

    @Override
    public void completeTask(WorkflowWaterMonthPlan workflowWaterMonthPlan) {
        String username = SecurityUtils.getUsername();
        Task task = taskService.createTaskQuery().taskAssignee(username).processInstanceId(workflowWaterMonthPlan.getInstanceId()).singleResult();
        if (Objects.isNull(task)) {
            log.info("{}没找到可以通过的任务", username);
        }
        taskService.setVariableLocal(task.getId(), "userName", SecurityUtils.getLoginUser().getUsername());
        taskService.setVariableLocal(task.getId(), "depId", SecurityUtils.getLoginUser().getUser().getDeptId());
        taskService.setVariableLocal(task.getId(), "comment", workflowWaterMonthPlan.getComment());
        taskService.complete(task.getId());
        workflowWaterMonthPlan.setAssignee(null);

        List<String> formKeyStrList = StrUtil.split(task.getFormKey(), "#");
        String nextRoleGroup = formKeyStrList.get(1);
        if (StringUtils.isEmpty(nextRoleGroup)) {
            workflowWaterMonthPlan.setState(WorkFlowConstants.WATER_PLAN_STATUS_ENUM.FINISH.getValue());
        }
        workflowWaterMonthPlan.setActivitiname(task.getName());
        workflowWaterMonthPlan.setRolegroup(nextRoleGroup);
        workflowWaterMonthPlan.setUpdateTime(new Date());
        workflowWaterMonthPlan.setUpdateBy(username);
        workflowWaterMonthPlanMapper.updateWorkflowWaterMonthPlan(workflowWaterMonthPlan);
    }

    @Override
    public void rejectTask(WorkflowWaterMonthPlan workflowWaterMonthPlan) {
        String username = SecurityUtils.getUsername();
        List<String> roles = StrUtil.split(workflowWaterMonthPlan.getRolegroup(), ",");
        Task task = taskService.createTaskQuery().taskCandidateGroupIn(roles).processInstanceId(workflowWaterMonthPlan.getInstanceId()).singleResult();
        if (Objects.isNull(task)) {
            log.info("{}没找到可以拒绝的任务", username);
        }
        List<String> formKeyStrList = StrUtil.split(task.getFormKey(), "#");
        String fromAcitivitiId = task.getTaskDefinitionKey(),
                toActivitiId = formKeyStrList.get(2);
        taskService.setVariableLocal(task.getId(), "userName", SecurityUtils.getLoginUser().getUsername());
        taskService.setVariableLocal(task.getId(), "depId", SecurityUtils.getLoginUser().getUser().getDeptId());
        dynamicJumpService.execution(workflowWaterMonthPlan.getInstanceId(), fromAcitivitiId, toActivitiId);
        workflowWaterMonthPlan.setAssignee(null);
        String backRoleGroup = formKeyStrList.get(0);
        if (StringUtils.isNotEmpty(backRoleGroup)) {
            workflowWaterMonthPlan.setRolegroup(backRoleGroup);
        }
        workflowWaterMonthPlan.setRolegroup(backRoleGroup);
        workflowWaterMonthPlan.setState(WorkFlowConstants.WATER_PLAN_STATUS_ENUM.REJECT.getValue());
        workflowWaterMonthPlan.setUpdateTime(new Date());
        workflowWaterMonthPlan.setUpdateBy(username);
        workflowWaterMonthPlanMapper.updateWorkflowWaterMonthPlan(workflowWaterMonthPlan);
    }

    @Override
    public int completeTaskByPlanID(Long planId) {
        WorkflowWaterMonthPlan workflowWaterMonthPlan = new WorkflowWaterMonthPlan();
        workflowWaterMonthPlan.setPlanId(planId);
        List<WorkflowWaterMonthPlan> workflowWaterMonthPlans = workflowWaterMonthPlanMapper.selectWorkflowWaterMonthPlanList(workflowWaterMonthPlan);
        if (CollectionUtil.isEmpty(workflowWaterMonthPlans)) {
            throw new CustomException("没找到可以审核的任务");
        }
        workflowWaterMonthPlan = workflowWaterMonthPlans.get(0);
        if (WorkFlowConstants.WATER_PLAN_STATUS_ENUM.FINISH.getValue().equals(workflowWaterMonthPlan.getState())) {
            throw new CustomException("已经结束的任务不可以审核");
        }
        claimTask(workflowWaterMonthPlan);
        completeTask(workflowWaterMonthPlan);

        // 通过
        BtFlowHistory btFlowHistory = new BtFlowHistory();
        btFlowHistory.setcDate(new Date());
        SysUser user = SecurityUtils.getLoginUser().getUser();
        btFlowHistory.setUserId(user.getUserId());
        btFlowHistory.setUserName(user.getNickName());
        btFlowHistory.setStatus("1");
        btFlowHistory.setReason("通过");
        btFlowHistory.setServiceId(planId);
        btFlowHistoryService.insertBtFlowHistory(btFlowHistory);

        return 1;
    }

    @Override
    public int rejectTaskByPlanID(Plan plan) {
        WorkflowWaterMonthPlan workflowWaterMonthPlan = new WorkflowWaterMonthPlan();
        workflowWaterMonthPlan.setPlanId(plan.getId());
        List<WorkflowWaterMonthPlan> workflowWaterMonthPlans = workflowWaterMonthPlanMapper.selectWorkflowWaterMonthPlanList(workflowWaterMonthPlan);
        if (CollectionUtil.isEmpty(workflowWaterMonthPlans)) {
            throw new CustomException("没找到可以拒绝的任务");
        }
        workflowWaterMonthPlan = workflowWaterMonthPlans.get(0);
        workflowWaterMonthPlan.setComment(plan.getReason());
        if (WorkFlowConstants.WATER_PLAN_STATUS_ENUM.FINISH.getValue().equals(workflowWaterMonthPlan.getState())) {
            throw new CustomException("已经结束的任务不可以驳回");
        }
        unClaimTask(workflowWaterMonthPlan);
        rejectTask(workflowWaterMonthPlan);
        // 开始节点提交历史信息
        BtFlowHistory btFlowHistory = new BtFlowHistory();
        btFlowHistory.setcDate(new Date());
        SysUser user = SecurityUtils.getLoginUser().getUser();
        btFlowHistory.setUserId(user.getUserId());
        btFlowHistory.setUserName(user.getNickName());
        btFlowHistory.setReason(plan.getReason());
        btFlowHistory.setStatus("2");
        btFlowHistory.setServiceId(plan.getId());
        btFlowHistoryService.insertBtFlowHistory(btFlowHistory);
        return 1;
    }

    /**
     * 月度计划审核-分页查询
     * @param workflowWaterMonthPlanVO
     * @return
     */
    @Override
    @DataScope(deptAlias = "sd", userAlias = "wwmp")
    public List<WorkflowWaterMonthPlanDTO> planReviewList(WorkflowWaterMonthPlanVO workflowWaterMonthPlanVO) {

        List<WorkflowWaterMonthPlanDTO> resworkflowWaterPlans = new ArrayList<>();
        List<WorkflowWaterMonthPlanDTO> workflowWaterMonthPlanDTOList = workflowWaterMonthPlanMapper.planReviewList(workflowWaterMonthPlanVO);
        List<String> userRoles = SecurityUtils.getLoginUser().getUser().getRoles().stream().map(SysRole::getRoleKey).collect(Collectors.toList());

        if (workflowWaterMonthPlanDTOList != null && !workflowWaterMonthPlanDTOList.isEmpty()) {
            for (WorkflowWaterMonthPlanDTO temp : workflowWaterMonthPlanDTOList) {
                Long deptId = SecurityUtils.getLoginUser().getUser().getDeptId();
                if(deptId == 100 || deptId == 103 || deptId == 105){
                    temp.setShowButton(true);
                    if(103 == deptId){
                        if("0".equals(temp.getType())){
                            continue;
                        }
                    }
                    if(105 == deptId){
                        if("1".equals(temp.getType())){
                            continue;
                        }
                    }
                }
                String processDefinitionKey = WorkFlowConstants.WATER_PLAN_CHANNEL.getEnum(temp.getChannel(), "month").getName();
                String waterPlanProcessDefinitionId = workFlowCache.getWaterPlanProcessDefinitionId(temp.getInstancdId(), processDefinitionKey);
                Collection<FlowElement> waterPlanFlowElementList = workFlowCache.getWaterPlanFlowElementList(waterPlanProcessDefinitionId);
                if(null == waterPlanFlowElementList){
                    continue;
                }
                int currentUserRoleSeq = 0, dbUserRoleSeq = 0, i = 0;
                Iterator<FlowElement> iterator = waterPlanFlowElementList.iterator();
                while (iterator.hasNext()) {
                    i++;
                    FlowElement flowElement = iterator.next();
                    if (flowElement instanceof UserTask) {
                        UserTask userTask = (UserTask) flowElement;
                        if (CollUtil.containsAny(userTask.getCandidateGroups(), userRoles)) {
                            currentUserRoleSeq = i;
                        }
                        if (CollUtil.containsAny(userTask.getCandidateGroups(), StrUtil.split(temp.getRolegroup(), ","))) {
                            dbUserRoleSeq = i;
                        }
                    }
                }
                int diffSeq = currentUserRoleSeq - dbUserRoleSeq;
                // 查询待提交
                if ("1".equals(workflowWaterMonthPlanVO.getReviewStatus()) && diffSeq == 0 && !"9".equals(temp.getState())) {
                    temp.setStatus("1");
                    resworkflowWaterPlans.add(temp);
                } else if ("2".equals(workflowWaterMonthPlanVO.getReviewStatus())) {
                    if ("9".equals(temp.getState())) {
                        temp.setStatus("2");
                    } else {
                        if (diffSeq <= -1) {
                            temp.setStatus("2");
                        } else {
                            continue;
                        }
                    }
                    resworkflowWaterPlans.add(temp);
                } else if ("3".equals(workflowWaterMonthPlanVO.getReviewStatus())) {
                    if ("9".equals(temp.getState())) {
                        temp.setStatus("2");
                    } else {
                        if (diffSeq == 0) {
                            temp.setStatus("1");
                        } else if (diffSeq <= -1) {
                            temp.setStatus("2");
                        } else {
                            continue;
                        }
                    }
                    resworkflowWaterPlans.add(temp);
                }
            }
        }
        return resworkflowWaterPlans;
    }

    /**
     * 审批农业信息
     * @param plan
     * @return
     */
    @Override
    public int examineAgriculturePlan(Plan plan) {
        if(null != plan.getPlanAgricultureAnnualList()){
            SwWaterMonthReport swWaterMonthReport = new SwWaterMonthReport();
            swWaterMonthReport.setId(plan.getId());
            swWaterMonthReport.setPlanAgricultureAnnualList(plan.getPlanAgricultureAnnualList());
            swWaterMonthReportService.addMonthReportDetail4Nongye(swWaterMonthReport);
        }
        return 1;
    }

    /**
     * 审批工业信息
     * @param plan
     * @return
     */
    @Override
    public int examineGyMonthPlan(Plan plan) {
        if(null != plan.getSwWaterMonthMeterList() && null != plan.getPlanAnnualList()){
            SwWaterMonthReport swWaterMonthReport = new SwWaterMonthReport();
            swWaterMonthReport.setId(plan.getId());
            swWaterMonthReport.setSwWaterMonthMeterList(plan.getSwWaterMonthMeterList());
            swWaterMonthReport.setPlanAnnualList(plan.getPlanAnnualList());
            swWaterMonthReportService.addMonthReportDetail(swWaterMonthReport);
        }
        return 1;
    }

}
